{% extends "base.html" %}
{% load static %}
{% block title %}报表统计 - 风之宿酒店管理系统{% endblock %}

{% block extra_css %}
<style type="text/tailwindcss">
@layer utilities {
    .card-shadow {
        box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
        transition: box-shadow 0.3s ease;
    }
    .card-shadow:hover {
        box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
    }
    .stat-card {
        @apply bg-white rounded-xl p-6 card-shadow transform transition-all duration-300 hover:-translate-y-1;
    }
    .section-title {
        @apply text-xl font-semibold text-gray-800 mb-4 flex items-center;
    }
    .section-title i {
        @apply mr-2 text-primary;
    }
    .chart-container {
        position: relative;
        transition: all 0.3s ease;
        width: 100%;
    }
    .chart-container:hover {
        filter: brightness(1.02);
        transform: translateY(-3px);
    }
    .chart-error {
        @apply absolute inset-0 flex flex-col items-center justify-center bg-gray-50 rounded-lg p-6 text-center;
    }
    .skeleton-loading {
        @apply absolute inset-0 bg-gray-100 animate-pulse rounded-lg;
        background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
        background-size: 200% 100%;
        animation: shimmer 1.5s infinite;
    }
    @keyframes shimmer {
        0% { background-position: -200% 0; }
        100% { background-position: 200% 0; }
    }
    .kpi-loading {
        @apply animate-pulse bg-gray-200 rounded w-1/3 h-8;
    }
    .error-toast {
        @apply fixed top-4 right-4 bg-red-50 border border-red-200 text-red-700 px-4 py-3 rounded-lg shadow-lg z-50 transform transition-all duration-300 translate-x-full opacity-0;
    }
    .error-toast.show {
        @apply translate-x-0 opacity-100;
    }
}
</style>
{% endblock %}

{% block content %}
<div class="container mx-auto px-4 py-8">
    <!-- 错误提示 -->
    <div id="errorToast" class="error-toast">
        <div class="flex">
            <div class="flex-shrink-0">
                <i class="fas fa-exclamation-circle"></i>
            </div>
            <div class="ml-3">
                <p id="toastMessage" class="text-sm font-medium"></p>
            </div>
            <button class="ml-auto pl-3 text-red-500 hover:text-red-700" onclick="hideErrorToast()">
                <i class="fas fa-times"></i>
            </button>
        </div>
    </div>

    <div class="mb-8">
        <h1 class="text-[clamp(1.8rem,3vw,2.5rem)] font-bold text-gray-800 mb-2">报表统计分析</h1>
        <p class="text-gray-600">全面了解酒店运营数据，包括入住率、应收款项和宾馆利用情况</p>
    </div>

    <!-- 时间范围选择器 -->
    <div class="bg-white rounded-xl p-4 card-shadow mb-6">
        <div class="flex flex-wrap items-center gap-4">
            <div class="flex items-center">
                <label for="startDate" class="text-gray-600 mr-2">开始日期:</label>
                <input type="date" id="startDate" class="border border-gray-300 rounded-md px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary">
            </div>
            <div class="flex items-center">
                <label for="endDate" class="text-gray-600 mr-2">结束日期:</label>
                <input type="date" id="endDate" class="border border-gray-300 rounded-md px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary">
            </div>
            <div class="flex items-center gap-2 ml-auto">
                <button id="todayBtn" class="px-4 py-2 bg-gray-100 hover:bg-gray-200 rounded-md text-sm transition-colors">今天</button>
                <button id="weekBtn" class="px-4 py-2 bg-gray-100 hover:bg-gray-200 rounded-md text-sm transition-colors">本周</button>
                <button id="monthBtn" class="px-4 py-2 bg-gray-100 hover:bg-gray-200 rounded-md text-sm transition-colors">本月</button>
                <button id="quarterBtn" class="px-4 py-2 bg-gray-100 hover:bg-gray-200 rounded-md text-sm transition-colors">本季度</button>
                <button id="yearBtn" class="px-4 py-2 bg-gray-100 hover:bg-gray-200 rounded-md text-sm transition-colors">今年</button>
                <button id="applyDateBtn" class="px-4 py-2 bg-primary text-white hover:bg-primary/90 rounded-md text-sm transition-colors">应用</button>
                <button id="autoUpdateBtn" class="px-4 py-2 bg-green-500 text-white hover:bg-green-600 rounded-md text-sm transition-colors">
                    <i class="fas fa-play mr-1"></i> 自动更新
                </button>
                <button id="stopUpdateBtn" class="px-4 py-2 bg-red-500 text-white hover:bg-red-600 rounded-md text-sm transition-colors hidden">
                    <i class="fas fa-stop mr-1"></i> 停止更新
                </button>
            </div>
        </div>
    </div>

    <!-- 关键指标卡片 -->
    <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
        <!-- 平均入住率 -->
        <div class="stat-card">
            <div class="flex justify-between items-start mb-4">
                <div>
                    <p class="text-gray-500 text-sm">平均入住率</p>
                    <h3 class="text-2xl font-bold text-gray-800 mt-1" id="avgOccupancyRate">
                        <span class="kpi-loading"></span>
                    </h3>
                </div>
                <div class="h-10 w-10 rounded-full bg-blue-100 flex items-center justify-center text-primary">
                    <i class="fas fa-bed"></i>
                </div>
            </div>
            <div class="flex items-center text-sm" id="occupancyTrend">
                <span class="text-gray-500">加载中...</span>
            </div>
        </div>

        <!-- 总应收金额 -->
        <div class="stat-card">
            <div class="flex justify-between items-start mb-4">
                <div>
                    <p class="text-gray-500 text-sm">总应收金额</p>
                    <h3 class="text-2xl font-bold text-gray-800 mt-1" id="totalReceivable">
                        <span class="kpi-loading"></span>
                    </h3>
                </div>
                <div class="h-10 w-10 rounded-full bg-green-100 flex items-center justify-center text-green-600">
                    <i class="fas fa-money-bill-wave"></i>
                </div>
            </div>
            <div class="flex items-center text-sm" id="receivableTrend">
                <span class="text-gray-500">加载中...</span>
            </div>
        </div>

        <!-- 平均宾馆利用率 -->
        <div class="stat-card">
            <div class="flex justify-between items-start mb-4">
                <div>
                    <p class="text-gray-500 text-sm">平均宾馆利用率</p>
                    <h3 class="text-2xl font-bold text-gray-800 mt-1" id="avgUtilizationRate">
                        <span class="kpi-loading"></span>
                    </h3>
                </div>
                <div class="h-10 w-10 rounded-full bg-purple-100 flex items-center justify-center text-purple-600">
                    <i class="fas fa-chart-pie"></i>
                </div>
            </div>
            <div class="flex items-center text-sm" id="utilizationTrend">
                <span class="text-gray-500">加载中...</span>
            </div>
        </div>

        <!-- 预订总数 -->
        <div class="stat-card">
            <div class="flex justify-between items-start mb-4">
                <div>
                    <p class="text-gray-500 text-sm">预订总数</p>
                    <h3 class="text-2xl font-bold text-gray-800 mt-1" id="totalBookings">
                        <span class="kpi-loading"></span>
                    </h3>
                </div>
                <div class="h-10 w-10 rounded-full bg-amber-100 flex items-center justify-center text-amber-600">
                    <i class="fas fa-calendar-check"></i>
                </div>
            </div>
            <div class="flex items-center text-sm" id="bookingsTrend">
                <span class="text-gray-500">加载中...</span>
            </div>
        </div>
    </div>

    <!-- 图表区域 -->
    <div class="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8">
        <!-- 入住率趋势图 -->
        <div class="lg:col-span-2 bg-white rounded-xl p-6 card-shadow">
            <h2 class="section-title">
                <i class="fas fa-chart-line"></i> 入住率趋势
            </h2>
            <div class="chart-container h-[350px]" id="occupancyChart">
                <!-- 骨架屏加载 -->
                <div class="skeleton-loading" id="occupancyChartLoader"></div>
            </div>
        </div>

        <!-- 宾馆类型占比 -->
        <div class="bg-white rounded-xl p-6 card-shadow">
            <h2 class="section-title">
                <i class="fas fa-chart-pie"></i> 宾馆类型占比
            </h2>
            <div class="chart-container h-[350px]" id="roomTypeChart">
                <div class="skeleton-loading" id="roomTypeChartLoader"></div>
            </div>
        </div>
    </div>

    <!-- 第二行图表 -->
    <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
        <!-- 应收金额趋势 -->
        <div class="bg-white rounded-xl p-6 card-shadow">
            <h2 class="section-title">
                <i class="fas fa-chart-bar"></i> 应收金额趋势
            </h2>
            <div class="chart-container h-[300px]" id="revenueChart">
                <div class="skeleton-loading" id="revenueChartLoader"></div>
            </div>
        </div>

        <!-- 宾馆利用率对比 -->
        <div class="bg-white rounded-xl p-6 card-shadow">
            <h2 class="section-title">
                <i class="fas fa-chart-column"></i> 宾馆利用率对比
            </h2>
            <div class="chart-container h-[300px]" id="utilizationChart">
                <div class="skeleton-loading" id="utilizationChartLoader"></div>
            </div>
        </div>
    </div>
</div>
{% endblock %}

{% block extra_js %}
<!-- 引入jQuery -->
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
<!-- 引入ECharts -->
<script src="{% static 'js/echarts.min.js' %}"></script>
<!-- 引入Font Awesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">

<script>
// 模块化组织代码
const ReportDashboard = (function() {
    // 私有变量
    const charts = {};
    let isEChartsLoaded = false;
    let isProcessing = false;
    let autoUpdateInterval = null;
    let currentData = null;

    // 图表颜色配置
    const colors = {
        primary: {
            main: '#3B82F6',
            light: 'rgba(59, 130, 246, 0.1)',
            gradient: ['#3B82F6', '#60A5FA']
        },
        secondary: {
            main: '#10B981',
            light: 'rgba(16, 185, 129, 0.1)',
            gradient: ['#10B981', '#34D399']
        },
        tertiary: {
            main: '#8B5CF6',
            light: 'rgba(139, 92, 246, 0.1)',
            gradient: ['#8B5CF6', '#A78BFA']
        },
        roomTypes: [
            '#3B82F6',  // 标准间 - 蓝色
            '#10B981',  // 豪华间 - 绿色
            '#8B5CF6',  // 套房 - 紫色
            '#F59E0B',  // 家庭房 - 琥珀色
            '#EF4444'   // 电竞房 - 红色
        ]
    };

    // 模拟数据生成器
    const DataGenerator = {
        // 生成随机数（带趋势）
        randomWithTrend(base, trend, volatility = 0.1) {
            const change = (Math.random() - 0.5) * volatility * base;
            return Math.max(0, base + trend * base + change);
        },

        // 生成时间序列标签
        generateDateLabels(days = 30) {
            const labels = [];
            const now = new Date();
            for (let i = days - 1; i >= 0; i--) {
                const date = new Date(now);
                date.setDate(now.getDate() - i);
                labels.push(date.toLocaleDateString('zh-CN', { month: '2-digit', day: '2-digit' }));
            }
            return labels;
        },

        // 生成入住率数据
        generateOccupancyData(days = 30) {
            const data = [];
            let baseOccupancy = 65; // 基础入住率65%
            
            for (let i = 0; i < days; i++) {
                // 周末入住率更高
                const dayOfWeek = (new Date().getDay() - days + 1 + i) % 7;
                const isWeekend = dayOfWeek === 0 || dayOfWeek === 6;
                const weekendBoost = isWeekend ? 15 : 0;
                
                // 随机波动
                const randomFactor = (Math.random() - 0.5) * 20;
                const occupancy = Math.min(95, Math.max(30, baseOccupancy + weekendBoost + randomFactor));
                data.push(Number(occupancy.toFixed(1)));
            }
            return data;
        },

        // 生成应收金额数据
        generateRevenueData(days = 30) {
            const data = [];
            let baseRevenue = 50000; // 基础收入5万元
            
            for (let i = 0; i < days; i++) {
                // 周末收入更高
                const dayOfWeek = (new Date().getDay() - days + 1 + i) % 7;
                const isWeekend = dayOfWeek === 0 || dayOfWeek === 6;
                const weekendBoost = isWeekend ? 20000 : 0;
                
                // 随机波动
                const randomFactor = (Math.random() - 0.5) * 30000;
                const revenue = Math.max(10000, baseRevenue + weekendBoost + randomFactor);
                data.push(Math.round(revenue));
            }
            return data;
        },

        // 生成房间类型数据
        generateRoomTypeData() {
            const types = ['标准间', '豪华间', '套房', '家庭房', '电竞房'];
            const data = [];
            
            for (let i = 0; i < types.length; i++) {
                // 每种房型有不同比例
                const baseCount = [120, 80, 50, 40, 30][i];
                const randomFactor = (Math.random() - 0.5) * 20;
                data.push(Math.max(10, Math.round(baseCount + randomFactor)));
            }
            return data;
        },

        // 生成宾馆利用率数据
        generateUtilizationData(days = 30) {
            const data = [];
            let baseUtilization = 70; // 基础利用率70%
            
            for (let i = 0; i < days; i++) {
                // 随机波动
                const randomFactor = (Math.random() - 0.5) * 25;
                const utilization = Math.min(98, Math.max(40, baseUtilization + randomFactor));
                data.push(Number(utilization.toFixed(1)));
            }
            return data;
        },

        // 生成总体统计数据
        generateOverallStats() {
            const occupancy = this.randomWithTrend(65, 0.02);
            const revenue = this.randomWithTrend(1500000, 0.05);
            const utilization = this.randomWithTrend(72, 0.01);
            const bookings = this.randomWithTrend(450, 0.03);

            // 生成趋势（随机但偏向正面）
            const trends = ['up', 'down', 'stable'];
            const trendWeights = [0.6, 0.2, 0.2]; // 60%概率上涨
            
            function getRandomTrend() {
                const rand = Math.random();
                let sum = 0;
                for (let i = 0; i < trends.length; i++) {
                    sum += trendWeights[i];
                    if (rand <= sum) return trends[i];
                }
                return 'stable';
            }

            function getChange(trend) {
                if (trend === 'up') return (Math.random() * 8 + 2).toFixed(1);
                if (trend === 'down') return (Math.random() * 5 + 1).toFixed(1);
                return '0.0';
            }

            const occupancyTrend = getRandomTrend();
            const revenueTrend = getRandomTrend();
            const utilizationTrend = getRandomTrend();
            const bookingsTrend = getRandomTrend();

            return {
                avg_occupancy_rate: Number(occupancy.toFixed(1)),
                total_receivable: Math.round(revenue),
                avg_utilization_rate: Number(utilization.toFixed(1)),
                total_bookings: Math.round(bookings),
                occupancy_trend: occupancyTrend,
                occupancy_change: getChange(occupancyTrend),
                receivable_trend: revenueTrend,
                receivable_change: getChange(revenueTrend),
                utilization_trend: utilizationTrend,
                utilization_change: getChange(utilizationTrend),
                bookings_trend: bookingsTrend,
                bookings_change: getChange(bookingsTrend)
            };
        },

        // 生成完整的模拟数据
        generateMockData(days = 30) {
            return {
                overall_stats: this.generateOverallStats(),
                occupancy_data: this.generateOccupancyData(days),
                revenue_data: this.generateRevenueData(days),
                room_type_data: this.generateRoomTypeData(),
                room_type_labels: ['标准间', '豪华间', '套房', '家庭房', '电竞房'],
                utilization_data: this.generateUtilizationData(days),
                utilization_labels: this.generateDateLabels(days),
                date_labels: this.generateDateLabels(days)
            };
        }
    };

    // 私有方法
    function checkEChartsLoaded() {
        return typeof echarts !== 'undefined';
    }

    function initCharts() {
        // 防止重复初始化
        if (!checkEChartsLoaded() || Object.keys(charts).length > 0) return;

        // 初始化所有图表
        charts.occupancyChart = echarts.init(document.getElementById('occupancyChart'));
        charts.revenueChart = echarts.init(document.getElementById('revenueChart'));
        charts.roomTypeChart = echarts.init(document.getElementById('roomTypeChart'));
        charts.utilizationChart = echarts.init(document.getElementById('utilizationChart'));

        // 响应窗口大小变化，调整图表尺寸
        $(window).on('resize', debounce(function() {
            Object.values(charts).forEach(chart => chart && chart.resize());
        }, 100));

        isEChartsLoaded = true;
    }

    function showChartError(chartId, message = '图表加载失败，请重试') {
        const container = $(`#${chartId}`);
        container.html(`
            <div class="chart-error">
                <i class="fas fa-exclamation-triangle text-amber-500 text-3xl mb-3"></i>
                <p class="text-gray-600 mb-3">${message}</p>
                <button class="text-primary hover:text-primary/80 focus:outline-none transition-colors" onclick="ReportDashboard.loadChartData()">
                    <i class="fas fa-sync-alt mr-1"></i> 重试
                </button>
            </div>
        `);
    }

    function hideLoader(loaderId) {
        const loader = $(`#${loaderId}`);
        if (loader.length) {
            loader.css('opacity', '0');
            setTimeout(() => loader.remove(), 300);
        }
    }

    function showLoader(loaderId) {
        const containerId = loaderId.replace('Loader', '');
        const container = $(`#${containerId}`);
        const existingLoader = $(`#${loaderId}`);

        if (!existingLoader.length) {
            const loader = $('<div>').attr('id', loaderId).addClass('skeleton-loading');
            container.append(loader);
        } else {
            existingLoader.css('opacity', '1');
        }

        // 重置KPI加载状态
        $('#avgOccupancyRate, #totalReceivable, #avgUtilizationRate, #totalBookings')
            .html('<span class="kpi-loading"></span>');
        $('#occupancyTrend, #receivableTrend, #utilizationTrend, #bookingsTrend')
            .html('<span class="text-gray-500">加载中...</span>');
    }

    function updateKpiIndicators(stats) {
        // 检查stats是否有效
        if (!stats || typeof stats !== 'object') {
            showErrorToast('无效的指标数据');
            return;
        }

        // 使用数字动画更新指标
        animateValue('avgOccupancyRate', stats.avg_occupancy_rate || 0, '%');
        animateValue('totalReceivable', stats.total_receivable || 0, '¥', true);
        animateValue('avgUtilizationRate', stats.avg_utilization_rate || 0, '%');
        animateValue('totalBookings', stats.total_bookings || 0, '');

        // 更新趋势指示器
        updateTrendIndicator('occupancyTrend', stats.occupancy_trend, stats.occupancy_change);
        updateTrendIndicator('receivableTrend', stats.receivable_trend, stats.receivable_change);
        updateTrendIndicator('utilizationTrend', stats.utilization_trend, stats.utilization_change);
        updateTrendIndicator('bookingsTrend', stats.bookings_trend, stats.bookings_change);
    }

    function animateValue(elementId, finalValue, suffix = '', isCurrency = false) {
        const element = document.getElementById(elementId);
        if (!element) return;

        // 确保finalValue是数字
        finalValue = parseFloat(finalValue) || 0;

        const startValue = 0;
        const duration = 1000; // 动画持续时间（毫秒）
        const frameDuration = 1000 / 60; // 每帧持续时间
        const totalFrames = Math.round(duration / frameDuration);
        let frame = 0;
        let animationId;

        // 清除可能存在的旧动画
        if (element.animationId) {
            clearInterval(element.animationId);
        }

        // 初始显示
        element.textContent = (isCurrency ? '¥' : '') + '0' + suffix;

        // 使用requestAnimationFrame实现更流畅的动画
        function updateAnimation() {
            frame++;
            const progress = frame / totalFrames;
            const currentValue = Math.round(progress * (finalValue - startValue) + startValue);

            if (isCurrency) {
                element.textContent = '¥' + currentValue.toLocaleString() + suffix;
            } else {
                element.textContent = currentValue + suffix;
            }

            if (frame < totalFrames) {
                animationId = requestAnimationFrame(updateAnimation);
            } else {
                // 确保显示最终精确值
                if (isCurrency) {
                    element.textContent = '¥' + finalValue.toLocaleString() + suffix;
                } else {
                    element.textContent = finalValue + suffix;
                }
            }
        }

        animationId = requestAnimationFrame(updateAnimation);
        element.animationId = animationId;
    }

    function updateTrendIndicator(elementId, trend, change) {
        const element = document.getElementById(elementId);
        if (!element) return;

        // 确保change是数字
        change = parseFloat(change) || 0;

        if (trend === 'up') {
            element.innerHTML = `<span class="text-green-500 flex items-center"><i class="fas fa-arrow-up mr-1"></i> ${change}%</span><span class="text-gray-500 ml-2">较上期</span>`;
        } else if (trend === 'down') {
            element.innerHTML = `<span class="text-red-500 flex items-center"><i class="fas fa-arrow-down mr-1"></i> ${change}%</span><span class="text-gray-500 ml-2">较上期</span>`;
        } else {
            element.innerHTML = `<span class="text-gray-500 flex items-center"><i class="fas fa-minus mr-1"></i> 0%</span><span class="text-gray-500 ml-2">较上期</span>`;
        }
    }

    function updateOccupancyChart(data, labels) {
        try {
            if (!charts.occupancyChart || !data || !labels) {
                throw new Error('数据不完整');
            }

            charts.occupancyChart.setOption({
                tooltip: {
                    trigger: 'axis',
                    backgroundColor: 'rgba(255, 255, 255, 0.95)',
                    borderColor: '#E5E7EB',
                    borderWidth: 1,
                    textStyle: { color: '#4B5563' },
                    formatter: '{b}: {c}%',
                    extraCssText: 'box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); border-radius: 8px;'
                },
                grid: {
                    left: '3%',
                    right: '4%',
                    bottom: '3%',
                    containLabel: true
                },
                xAxis: {
                    type: 'category',
                    boundaryGap: false,
                    data: labels,
                    axisLine: {
                        lineStyle: {
                            color: 'rgba(0, 0, 0, 0.05)'
                        }
                    },
                    axisLabel: {
                        color: '#6B7280',
                        fontSize: 11
                    }
                },
                yAxis: {
                    type: 'value',
                    max: 100,
                    axisLine: {
                        show: false
                    },
                    axisLabel: {
                        color: '#6B7280',
                        fontSize: 11,
                        formatter: '{value}%'
                    },
                    splitLine: {
                        lineStyle: {
                            color: 'rgba(0, 0, 0, 0.05)'
                        }
                    }
                },
                series: [
                    {
                        name: '入住率',
                        type: 'line',
                        data: data,
                        smooth: true,
                        symbol: 'none',
                        sampling: 'average',
                        itemStyle: {
                            color: colors.primary.main
                        },
                        lineStyle: {
                            width: 3,
                            color: colors.primary.main
                        },
                        areaStyle: {
                            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                                { offset: 0, color: colors.primary.gradient[0] },
                                { offset: 1, color: colors.primary.light }
                            ])
                        },
                        emphasis: {
                            scale: true,
                            itemStyle: {
                                shadowBlur: 10,
                                shadowColor: 'rgba(0, 0, 0, 0.3)'
                            }
                        },
                        animationDuration: 1500,
                        animationEasing: 'cubicOut'
                    }
                ]
            });
        } catch (error) {
            console.error('Error updating occupancy chart:', error);
            showChartError('occupancyChart', '入住率图表加载失败');
        }
    }

    function updateRevenueChart(data, labels) {
        try {
            if (!charts.revenueChart || !data || !labels) {
                throw new Error('数据不完整');
            }

            charts.revenueChart.setOption({
                tooltip: {
                    trigger: 'axis',
                    backgroundColor: 'rgba(255, 255, 255, 0.95)',
                    borderColor: '#E5E7EB',
                    borderWidth: 1,
                    textStyle: { color: '#4B5563' },
                    formatter: '{b}: ¥{c}',
                    extraCssText: 'box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); border-radius: 8px;'
                },
                grid: {
                    left: '3%',
                    right: '4%',
                    bottom: '3%',
                    containLabel: true
                },
                xAxis: {
                    type: 'category',
                    data: labels,
                    axisLine: {
                        lineStyle: {
                            color: 'rgba(0, 0, 0, 0.05)'
                        }
                    },
                    axisLabel: {
                        color: '#6B7280',
                        fontSize: 11
                    }
                },
                yAxis: {
                    type: 'value',
                    axisLine: {
                        show: false
                    },
                    axisLabel: {
                        color: '#6B7280',
                        fontSize: 11,
                        formatter: '¥{value}'
                    },
                    splitLine: {
                        lineStyle: {
                            color: 'rgba(0, 0, 0, 0.05)'
                        }
                    }
                },
                series: [
                    {
                        name: '应收金额',
                        type: 'bar',
                        data: data,
                        itemStyle: {
                            borderRadius: 6,
                            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                                { offset: 0, color: colors.secondary.gradient[0] },
                                { offset: 1, color: colors.secondary.gradient[1] }
                            ])
                        },
                        barWidth: '60%',
                        animationDuration: 1500,
                        animationEasing: 'cubicOut'
                    }
                ]
            });
        } catch (error) {
            console.error('Error updating revenue chart:', error);
            showChartError('revenueChart', '应收金额图表加载失败');
        }
    }

    function updateRoomTypeChart(data, labels) {
        try {
            if (!charts.roomTypeChart || !data || !labels) {
                throw new Error('数据不完整');
            }

            charts.roomTypeChart.setOption({
                tooltip: {
                    trigger: 'item',
                    backgroundColor: 'rgba(255, 255, 255, 0.95)',
                    borderColor: '#E5E7EB',
                    borderWidth: 1,
                    textStyle: { color: '#4B5563' },
                    formatter: '{a} <br/>{b}: {c}间 ({d}%)',
                    extraCssText: 'box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); border-radius: 8px;'
                },
                legend: {
                    orient: 'vertical',
                    bottom: 10,
                    left: 'center',
                    textStyle: {
                        color: '#6B7280',
                        fontSize: 12
                    },
                    icon: 'circle',
                    itemWidth: 10,
                    itemHeight: 10,
                    itemGap: 15
                },
                series: [
                    {
                        name: '宾馆类型',
                        type: 'pie',
                        radius: ['60%', '80%'],
                        center: ['50%', '45%'],
                        avoidLabelOverlap: false,
                        itemStyle: {
                            borderRadius: 6,
                            borderColor: '#fff',
                            borderWidth: 2
                        },
                        label: {
                            show: false,
                            position: 'center'
                        },
                        emphasis: {
                            label: {
                                show: true,
                                fontSize: 16,
                                fontWeight: 'bold',
                                color: '#1F2937'
                            }
                        },
                        labelLine: {
                            show: false
                        },
                        data: labels.map((label, index) => ({
                            value: data[index] || 0,
                            name: label,
                            itemStyle: {
                                color: colors.roomTypes[index % colors.roomTypes.length]
                            }
                        })),
                        animationDuration: 1500,
                        animationEasingUpdate: 'cubicOut'
                    }
                ]
            });
        } catch (error) {
            console.error('Error updating room type chart:', error);
            showChartError('roomTypeChart', '宾馆类型图表加载失败');
        }
    }

    function updateUtilizationChart(data, labels) {
        try {
            if (!charts.utilizationChart || !data || !labels) {
                throw new Error('数据不完整');
            }

            charts.utilizationChart.setOption({
                tooltip: {
                    trigger: 'axis',
                    backgroundColor: 'rgba(255, 255, 255, 0.95)',
                    borderColor: '#E5E7EB',
                    borderWidth: 1,
                    textStyle: { color: '#4B5563' },
                    formatter: '{b}: {c}%',
                    extraCssText: 'box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); border-radius: 8px;'
                },
                grid: {
                    left: '3%',
                    right: '4%',
                    bottom: '3%',
                    containLabel: true
                },
                xAxis: {
                    type: 'category',
                    data: labels,
                    axisLine: {
                        lineStyle: {
                            color: 'rgba(0, 0, 0, 0.05)'
                        }
                    },
                    axisLabel: {
                        color: '#6B7280',
                        fontSize: 11
                    }
                },
                yAxis: {
                    type: 'value',
                    max: 100,
                    axisLine: {
                        show: false
                    },
                    axisLabel: {
                        color: '#6B7280',
                        fontSize: 11,
                        formatter: '{value}%'
                    },
                    splitLine: {
                        lineStyle: {
                            color: 'rgba(0, 0, 0, 0.05)'
                        }
                    }
                },
                series: [
                    {
                        name: '利用率',
                        type: 'bar',
                        data: data,
                        itemStyle: {
                            borderRadius: 6,
                            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                                { offset: 0, color: colors.tertiary.gradient[0] },
                                { offset: 1, color: colors.tertiary.gradient[1] }
                            ])
                        },
                        barWidth: '60%',
                        animationDuration: 1500,
                        animationEasing: 'cubicOut'
                    }
                ]
            });
        } catch (error) {
            console.error('Error updating utilization chart:', error);
            showChartError('utilizationChart', '宾馆利用率图表加载失败');
        }
    }

    function debounce(func, wait) {
        let timeout;
        return function(...args) {
            const context = this;
            clearTimeout(timeout);
            timeout = setTimeout(() => func.apply(context, args), wait);
        };
    }

    function processChartData(chartData) {
        // 防止重复处理
        if (isProcessing) return;
        isProcessing = true;

        try {
            // 检查数据是否有效
            if (!chartData || typeof chartData !== 'object') {
                throw new Error('无效的报表数据');
            }

            // 更新关键指标
            updateKpiIndicators(chartData.overall_stats);

            // 更新图表
            updateOccupancyChart(chartData.occupancy_data, chartData.date_labels);
            updateRevenueChart(chartData.revenue_data, chartData.date_labels);
            updateRoomTypeChart(chartData.room_type_data, chartData.room_type_labels);
            updateUtilizationChart(chartData.utilization_data, chartData.utilization_labels);

            // 隐藏加载状态
            ['occupancyChartLoader', 'revenueChartLoader', 'roomTypeChartLoader', 'utilizationChartLoader']
                .forEach(hideLoader);

            // 存储当前数据
            currentData = chartData;

        } catch (error) {
            console.error('Error processing chart data:', error);
            handleDataError(error.message);
            showErrorToast(error.message);
        } finally {
            isProcessing = false;
        }
    }

    function handleDataError(message = '数据加载失败，请重试') {
        // 隐藏加载状态并显示错误
        ['occupancyChartLoader', 'revenueChartLoader', 'roomTypeChartLoader', 'utilizationChartLoader']
            .forEach(hideLoader);

        ['occupancyChart', 'revenueChart', 'roomTypeChart', 'utilizationChart']
            .forEach(chartId => showChartError(chartId, message));

        // 更新KPI显示错误
        $('#avgOccupancyRate, #totalReceivable, #avgUtilizationRate, #totalBookings').text('--');
        $('.trend-indicator').html(`<span class="text-red-500">${message}</span>`);
    }

    // 错误提示弹窗
    function showErrorToast(message) {
        const toast = $('#errorToast');
        $('#toastMessage').text(message);
        toast.addClass('show');

        // 5秒后自动隐藏
        setTimeout(() => hideErrorToast(), 5000);
    }

    function hideErrorToast() {
        const toast = $('#errorToast');
        toast.removeClass('show');
    }

    // 生成模拟数据
    function generateMockData(startDate = null, endDate = null) {
        // 计算天数
        let days = 30; // 默认30天
        if (startDate && endDate) {
            const start = new Date(startDate);
            const end = new Date(endDate);
            days = Math.ceil((end - start) / (1000 * 60 * 60 * 24)) + 1;
            days = Math.min(Math.max(days, 7), 365); // 限制在7-365天之间
        }

        return DataGenerator.generateMockData(days);
    }

    // 自动更新数据
    function startAutoUpdate() {
        if (autoUpdateInterval) return;

        autoUpdateInterval = setInterval(() => {
            const startDate = $('#startDate').val();
            const endDate = $('#endDate').val();
            const mockData = generateMockData(startDate, endDate);
            processChartData(mockData);
        }, 3000); // 每3秒更新一次

        $('#autoUpdateBtn').addClass('hidden');
        $('#stopUpdateBtn').removeClass('hidden');
    }

    function stopAutoUpdate() {
        if (autoUpdateInterval) {
            clearInterval(autoUpdateInterval);
            autoUpdateInterval = null;
        }

        $('#autoUpdateBtn').removeClass('hidden');
        $('#stopUpdateBtn').addClass('hidden');
    }

    // 初始化日期选择器
    function initDatePickers() {
        // 设置默认日期范围为最近30天
        const today = new Date();
        const thirtyDaysAgo = new Date();
        thirtyDaysAgo.setDate(today.getDate() - 30);

        $('#startDate').val(thirtyDaysAgo.toISOString().split('T')[0]);
        $('#endDate').val(today.toISOString().split('T')[0]);

        // 日期范围快捷按钮
        $('#todayBtn').click(() => {
            const date = new Date().toISOString().split('T')[0];
            $('#startDate').val(date);
            $('#endDate').val(date);
        });

        $('#weekBtn').click(() => {
            const today = new Date();
            const weekAgo = new Date();
            weekAgo.setDate(today.getDate() - 7);

            $('#startDate').val(weekAgo.toISOString().split('T')[0]);
            $('#endDate').val(today.toISOString().split('T')[0]);
        });

        $('#monthBtn').click(() => {
            const today = new Date();
            const monthAgo = new Date();
            monthAgo.setMonth(today.getMonth() - 1);

            $('#startDate').val(monthAgo.toISOString().split('T')[0]);
            $('#endDate').val(today.toISOString().split('T')[0]);
        });

        $('#quarterBtn').click(() => {
            const today = new Date();
            const quarterAgo = new Date();
            quarterAgo.setMonth(today.getMonth() - 3);

            $('#startDate').val(quarterAgo.toISOString().split('T')[0]);
            $('#endDate').val(today.toISOString().split('T')[0]);
        });

        $('#yearBtn').click(() => {
            const today = new Date();
            const yearAgo = new Date();
            yearAgo.setFullYear(today.getFullYear() - 1);

            $('#startDate').val(yearAgo.toISOString().split('T')[0]);
            $('#endDate').val(today.toISOString().split('T')[0]);
        });

        // 应用日期范围
        $('#applyDateBtn').click(() => {
            const startDate = $('#startDate').val();
            const endDate = $('#endDate').val();

            if (startDate && endDate && new Date(startDate) > new Date(endDate)) {
                showErrorToast('开始日期不能晚于结束日期');
                return;
            }

            const mockData = generateMockData(startDate, endDate);
            processChartData(mockData);
        });

        // 自动更新按钮
        $('#autoUpdateBtn').click(startAutoUpdate);
        $('#stopUpdateBtn').click(stopAutoUpdate);
    }

    // 公共方法
    return {
        loadChartData: function(startDate = null, endDate = null) {
            // 检查ECharts是否加载，如果未加载则尝试重新加载
            if (!checkEChartsLoaded()) {
                // 尝试重新加载ECharts
                const script = document.createElement('script');
                script.src="{% static 'js/echarts.min.js' %}";
                script.onload = function() {
                    initCharts();
                    const mockData = generateMockData(startDate, endDate);
                    processChartData(mockData);
                };
                script.onerror = function() {
                    const errorMsg = 'ECharts加载失败，请检查文件路径';
                    handleDataError(errorMsg);
                    showErrorToast(errorMsg);
                };
                document.head.appendChild(script);
            } else {
                // 已加载，直接处理数据
                initCharts();
                const mockData = generateMockData(startDate, endDate);
                processChartData(mockData);
            }
        },
        startAutoUpdate: startAutoUpdate,
        stopAutoUpdate: stopAutoUpdate,
        init: function() {
            // 页面加载完成后初始化
            $(document).ready(function() {
                // 初始化日期选择器
                initDatePickers();

                // 检查ECharts是否已在base.html中加载
                if (checkEChartsLoaded()) {
                    initCharts();
                    this.loadChartData();
                } else {
                    // 尝试加载ECharts
                    this.loadChartData();
                }
            }.bind(this));
        }
    };
})();

// 初始化报表仪表板
ReportDashboard.init();
</script>
{% endblock %}